package com.fengke.dao.sn.impl;

import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Date;

import com.fengke.dao.BaseDaoIbatis;
import com.fengke.dao.model.Sn;
import com.fengke.dao.model.Sn.Type;
import com.fengke.dao.sn.SnManager;
import com.fengke.util.Constants;
/**
 * sn 生成器
 * 
 */
public class SnManagerImpl extends BaseDaoIbatis implements SnManager {
	private HiloOptimizer productHiloOptimizer;
	private HiloOptimizer orderHiloOptimizer;
	private HiloOptimizer paymentHiloOptimizer;
	private HiloOptimizer refundsHiloOptimizer;
	private HiloOptimizer shippingHiloOptimizer;
	private HiloOptimizer returnsHiloOptimizer;
	public SnManagerImpl() {
		productHiloOptimizer = new HiloOptimizer(Type.product, Constants.SnGenerator.SN_PRODUCT_PREFIX, Constants.SnGenerator.SN_PRODUCT_MAXLO);
		orderHiloOptimizer = new HiloOptimizer(Type.order, Constants.SnGenerator.SN_ORDER_PREFIX, Constants.SnGenerator.SN_ORDER_MAXLO);
		paymentHiloOptimizer = new HiloOptimizer(Type.payment, Constants.SnGenerator.SN_PAYMENT_PREFIX, Constants.SnGenerator.SN_PAYMENT_MAXLO);
		refundsHiloOptimizer = new HiloOptimizer(Type.refunds, Constants.SnGenerator.SN_REFUNDS_PREFIX, Constants.SnGenerator.SN_REFUNDS_MAXLO);
		shippingHiloOptimizer = new HiloOptimizer(Type.shipping, Constants.SnGenerator.SN_SHIPPING_PREFIX, Constants.SnGenerator.SN_SHIPPING_MAXLO);
		returnsHiloOptimizer = new HiloOptimizer(Type.returns, Constants.SnGenerator.SN_RETURNS_PREFIX, Constants.SnGenerator.SN_RETURNS_MAXLO);
	}
	
	public String generate(Type type) throws SQLException {
		if (type == Type.product) {
			return productHiloOptimizer.generate();
		} else if (Type.order.equals(type)) {
			return orderHiloOptimizer.generate();
		} else if (Type.payment.equals(type)) {
			return paymentHiloOptimizer.generate();
		} else if (Type.refunds.equals(type)) {
			return refundsHiloOptimizer.generate();
		} else if (Type.shipping.equals(type)) {
			return shippingHiloOptimizer.generate();
		} else if (Type.returns.equals(type)) {
			return returnsHiloOptimizer.generate();
		}
		return null;
	}
	
	private long getLastValue(Type type) {
		Sn sn = new Sn();
		sn.setType(type);
		sn = (Sn) this.getSqlMapClientTemplate().queryForObject("MasterRepository.researchSnByType", sn);
		if(sn != null) {
			long lastValue = sn.getLastValue();
			sn.setLastValue(lastValue + 1);
			sn.setModifyDate(new Date());
			this.getSqlMapClientTemplate().update("MasterRepository.updateSnByType", sn);
			return lastValue;
		}
		
		return 0;
	}
	
	/**
	 * 高低位算法
	 */
	private class HiloOptimizer {

		private Type type;
		private String prefix;
		private int maxLo;
		private int lo;
		private long hi;
		private long lastValue;

		public HiloOptimizer(Type type, String prefix, int maxLo) {
			this.type = type;
			this.prefix = prefix;
			this.maxLo = maxLo;
			this.lo = maxLo + 1;
		}

		public synchronized String generate() {
			if (lo > maxLo) {
				lastValue = getLastValue(type);
				lo = lastValue == 0 ? 1 : 0;
				hi = lastValue * (maxLo + 1);
			}
			SimpleDateFormat sdf = new SimpleDateFormat(prefix);
			
			return sdf.format(new Date()) + (hi + lo++);
		}

	}
}
